/******************************************************************
 * @version      : 1.0
 * @Author       : zhl
 * @Date         : 2023-06-27 17:05:17
 * @LastEditors  : zhl
 * @E-Mail       : zhll168@163.com
 * @Description  : 业务描述
 ******************************************************************/
#include <string.h>
#include <iostream>
#include "DLT698Manager.h"
#include "DLT698-Frame.h"
#include "check_code.h"
#include "hex.h"


DLT698Manager DLT698Manager::c_dlt698_manager;

DLT698Manager::DLT698Manager(/* args */){
}

DLT698Manager::~DLT698Manager(){
}

DLT698Manager& DLT698Manager::get_instance(){
    return c_dlt698_manager;
}
/**
 * @brief 签到码设置
 **/
void  DLT698Manager::set_lead_code(DLT698_FRAME& dlt698_frame, uint8_t *lc){
    if(NULL == lc){
        c_is_lead_code = false;
    }else{
        memcpy(c_dlt698_frame.lc, lc, sizeof(c_dlt698_frame.lc));
        c_is_lead_code = true;
    }
}
/**
 * @brief 扰码设置
 **/
void  DLT698Manager::set_scrambling_code(DLT698_FRAME& dlt698_frame, uint8_t sbc){
    c_dlt698_frame.sbc = sbc;
}
/**
 * @brief 控制码设置
 **/
void  DLT698Manager::set_control_code(DLT698_FRAME& dlt698_frame, uint8_t c){
    c_dlt698_frame.c.value = c;
}
/**
 * @brief 从站地址设置
 **/
int DLT698Manager::set_slave_addr(DLT698_FRAME& dlt698_frame, std::string slave_addr){
    if(slave_addr.empty()){
        return 0;
    }
    int offset = 0;
    int sa_l = 16;
    unsigned char s_a[sa_l] = {0};
    if((slave_addr.length()%2) != 0){
        slave_addr += "F";
    }
    if( 0 == str_to_hex((const char *)slave_addr.c_str(), s_a, &sa_l)){
        c_dlt698_frame.sa_fc.sa_fc.addr_len = sa_l - 1;
        for(int j = --sa_l; j >=0; j--){
            memcpy(c_dlt698_frame.sa+offset, s_a+j, 1);
            offset += 1;
        }
    }
    
    return offset;
}

void DLT698Manager::init(){
    c_is_lead_code = false;
}

int DLT698Manager::packet_frame(DLT698_FRAME& dlt698_frame, uint8_t *frame, int frame_len, APDU &apdu){

    if((NULL == frame) || (1 > frame_len) || (NULL == apdu.apdu) || (frame_len < apdu.apdu_len)){
        return -1;
    }
    int offset = 0;
    int cs_start = 0;
    int hcs_offset = 0;
    //前导码
    if(c_is_lead_code){
        memcpy(frame, dlt698_frame.lc, sizeof(dlt698_frame.lc));
        offset += sizeof(dlt698_frame.lc);
        cs_start += sizeof(dlt698_frame.lc);
    }
    //起始码
    memcpy(frame+offset, &(dlt698_frame.sc), sizeof(dlt698_frame.sc));
    offset += sizeof(dlt698_frame.sc);
    cs_start += sizeof(dlt698_frame.sc);
    //长度
    offset += sizeof(dlt698_frame.l);
    //控制域
    memcpy(frame+offset, &dlt698_frame.c.value, sizeof(dlt698_frame.c.value));
    offset += sizeof(dlt698_frame.c.value);
    //地址域
    memcpy(frame+offset, &dlt698_frame.sa_fc.value, sizeof(dlt698_frame.sa_fc.value));
    offset += sizeof(dlt698_frame.sa_fc.value);
    memcpy(frame+offset, dlt698_frame.sa, dlt698_frame.sa_fc.sa_fc.addr_len+1);
    offset += dlt698_frame.sa_fc.sa_fc.addr_len+1;
    //客户机地址ca
    memcpy(frame+offset, &dlt698_frame.ca, sizeof(dlt698_frame.ca));
    offset += sizeof(dlt698_frame.ca);
    //帧头校验 跳过
    hcs_offset = offset;
    offset += sizeof(uint16_t);
    //apdu
    if(1 == dlt698_frame.c.control_code.sc){
        for(int i = 0; i < apdu.apdu_len; i++){
            frame[offset] = frame[i]+dlt698_frame.sbc;
            offset++;
        }
    }else{
        memcpy(frame+offset, apdu.apdu, apdu.apdu_len);
        offset += apdu.apdu_len;
    }
    //长度 需要加上尾部校验码的长度
    decltype(dlt698_frame.l) ll = offset-cs_start+sizeof(uint16_t);
    memcpy(frame+cs_start, &ll, sizeof(dlt698_frame.l));
    //帧头校验hcs
    uint16_t cs = get_fcs16(PPPINITFCS16, frame+cs_start, hcs_offset-cs_start);
    memcpy(frame+hcs_offset, &cs, sizeof(uint16_t));
    //帧校验fcs 赋值
    cs = get_fcs16(PPPINITFCS16, frame+cs_start, offset-cs_start);
    memcpy(frame+offset, &cs, sizeof(uint16_t));
    offset += sizeof(uint16_t);
    //结束符
    memcpy(frame+offset, &dlt698_frame.em, sizeof(dlt698_frame.em));
    offset += sizeof(dlt698_frame.em);
    
    return offset;
}